-- @author SolarEdge 2023 - 2025

local ZomboWin = require("ZomboWin/ZomboWin")
require("ZomboWin/BodyCount")
require("ZomboWin/ZLMain")

-- Traumatized trait settings
--local player:getModData().timedHandler.hoursSinceLastDefeat = 0;
local hoursToNormal = 0;
local durationDecode = 0;

local function initData()
	local player = getPlayer();
	local optionMax = (SandboxVars.ZomboWin.banditLimit)
	local slimitMax = 0;
	local limitMax = 0;
	player:getModData().timedHandler = player:getModData().timedHandler or {};
	player:getModData().timedHandler.hoursSinceLastDefeat = player:getModData().timedHandler.hoursSinceLastDefeat or 0;
	player:getModData().slimitMax = player:getModData().slimitMax or 1;
	
	if slimitMax ~= nil then 
		--- codes here ---
		if optionMax == 2 then
			limitMax = 1;
		elseif optionMax == 3 then
			limitMax = 2;
		elseif optionMax == 4 then
			limitMax = 4;
		end
		if player:HasTrait("swinger") then limitMax = (limitMax * 2); end
		if player:HasTrait("promiscuous") then limitMax = -1; end
		if player:HasTrait("Rapist") then limitMax = -1; end
		
		if optionMax == 1 then limitMax = -1; end
		
		player:getModData().slimitMax = limitMax; 
		Check(player);
	end
end

local function initDataV2()
	local player = getPlayer();
	local optionMax = (SandboxVars.ZomboWin.banditLimit)
	local slimitMax = 0;
	local limitMax = 0;
	player:getModData().timedHandler = player:getModData().timedHandler or {};
	player:getModData().timedHandler.hoursSinceLastDefeat = player:getModData().timedHandler.hoursSinceLastDefeat or 0;
	player:getModData().slimitMax = player:getModData().slimitMax or 1;
	
	if slimitMax ~= nil then 
		--- codes here ---
		if optionMax == 2 then
			limitMax = 1;
		elseif optionMax == 3 then
			limitMax = 2;
		elseif optionMax == 4 then
			limitMax = 4;
		end
		if player:HasTrait("swinger") then limitMax = (limitMax * 2); end
		if player:HasTrait("promiscuous") then limitMax = -1; end
		if player:HasTrait("Rapist") then limitMax = -1; end
		
		if optionMax == 1 then limitMax = -1; end
		
		player:getModData().slimitMax = limitMax; 
		Check(player);
	end
	------- Clean Up -------
	disabler(player, false);
	zwPlayerReset(player);
	------------------------
end

local function limitTimer(player)
	local hoursToWait = 12
	local slimitMax = player:getModData().slimitMax

	player:getModData().byCount = player:getModData().byCount or {};
	local byCount = player:getModData().byCount
	
	if SandboxVars.ZomboWin.banditRewardNew == 1 then
		hoursToWait = 6;
	elseif SandboxVars.ZomboWin.banditRewardNew == 2 then
		hoursToWait = 12;
	elseif SandboxVars.ZomboWin.banditRewardNew == 3 then
		hoursToWait = 18;
	else
		hoursToWait = 24;
	end
		
	local function updateHistory(player)
		if #byCount > 0 then
			for i = #byCount, 1, -1 do -- Iterate backwards to safely remove items
				local oHistory = byCount[i]
				if oHistory and instanceof(oHistory, "IsoZombie") then
					oHistory:getModData().sFoodsNew = oHistory:getModData().sFoodsNew or 0;
					oHistory:getModData().sFoodsNew = oHistory:getModData().sFoodsNew + 1;
					if oHistory:getModData().sFoodsNew >= hoursToWait then
						oHistory:getModData().sFoodsNew = 0;
						oHistory:getModData().sFoods = 0;
						table.remove(byCount, i);
						--HaloTextHelper.addTextWithArrow(player, getText("Sexual Limit Count: ") .. #byCount .. getText(" of ") .. player:getModData().slimitMax, false, HaloTextHelper.getColorGreen());
					end
				end
			end
		end
	end
	
	updateHistory(player);
	Check(player);
end

local function traumatizeTimer()
	-- Traumatized Counter
	local player = getPlayer();
	if player == nil then
		return;
	end	
	
	initData();
	limitTimer(player);
		
	if player:HasTrait("Traumatized") then
		--print("Traumatized - 1!");
		player:getModData().timedHandler.hoursSinceLastDefeat = player:getModData().timedHandler.hoursSinceLastDefeat + 1

		durationDecode = (SandboxVars.ZomboWin.tLength * 0.1);
		if durationDecode == 0.1 then
			hoursToNormal = 0; player:getModData().timedHandler.hoursSinceLastDefeat = 0;	-- None
		elseif durationDecode == 0.2 then 
			hoursToNormal = 3 + ZombRand(4); -- 3-6 hours
		elseif durationDecode == 0.3 then 
			hoursToNormal = 6 + ZombRand(7); -- 6-12 hours
		elseif durationDecode == 0.4 then 
			hoursToNormal = 24 + ZombRand(25); -- 1-2 days
		elseif durationDecode == 0.5 then 
			hoursToNormal = 72 + ZombRand(49); -- 3-5 days
		elseif durationDecode == 0.6 then 
			hoursToNormal = 120 + ZombRand(49); -- 5-7 days
		end
		
		if player:getModData().timedHandler.hoursSinceLastDefeat >= hoursToNormal then
			HaloTextHelper.addTextWithArrow(player, getText("Traumatized"), false, HaloTextHelper.getColorGreen());
			player:getTraits():remove("Traumatized")
			player:getModData().timedHandler.hoursSinceLastDefeat = 0;
			return
		end
	end
end

local function traitHygienes()
	local player = getPlayer();
	local filth = player:getHumanVisual();
	local dirtL = 0;
	local bloodL = 0;
	local totalFilth = 0;
	local threshlv1 = 3;
	local threshlv2 = 5;
	
	local stressCaplv1 = 35;
	local stressCaplv2 = 20;
	
	local function round(number)
		return math.floor(number + 0.5);
	end
	
	local function benefitsPlus(player, unha, stre, pani, sick)
		local stats = player:getStats();
		local bodyDamage = player:getBodyDamage();
		local unhappiness = bodyDamage:getUnhappynessLevel();
		local stress = stats:getStress();
		local panic = stats:getPanic();
		local sickness = bodyDamage:getFoodSicknessLevel()
		
		if unhappiness > 0 then
			bodyDamage:setUnhappynessLevel(unhappiness - unha);
		end
		if stress > 0 then
			stats:setStress(stress - stre);
		end
		if panic > 0 then
			stats:setPanic(panic - pani);
		end
		if sickness > 0 then
			bodyDamage:setFoodSicknessLevel(sickness - sick)
		end
	end
	
	for i = 0, BloodBodyPartType.MAX:index() - 1 do
		local bloodBodyPartType = BloodBodyPartType.FromIndex(i)
		dirtL = dirtL + filth:getDirt(bloodBodyPartType);
	end
	
	for i = 0, BloodBodyPartType.MAX:index() - 1 do
		local bloodBodyPartType = BloodBodyPartType.FromIndex(i)
		bloodL = bloodL + filth:getBlood(bloodBodyPartType);
	end
	
	totalFilth = round(dirtL + bloodL);
	print("total filth: " .. totalFilth);
--[[		--- [bug]: attempted index: setStress of non-table: null
	if player:HasTrait("neatTidy") then
		if totalFilth > threshlv2 then
			stats:setStress(stress + 4);
		else
			benefitsPlus(player, 3, 3, 3, 3)
		end
	elseif player:HasTrait("lovesClean") then
		if totalFilth > threshlv1 then
			if stress < stressCaplv1 then
				stats:setStress(stress + 7);
			end
		else
			benefitsPlus(player, 6, 6, 6, 6)
		end
	end
]]
end

local function TestingFunction()
	print("Calling testing function!!")
	if player:getModData().timedHandler.hoursSinceLastDefeat ~= nil then
		if player:getModData().timedHandler.hoursSinceLastDefeat >= 0 then
			local hoursString = tostring(player:getModData().timedHandler.hoursSinceLastDefeat);
			print(hoursString);
		end
	elseif player:getModData().timedHandler.hoursSinceLastDefeat == nil then
		print("player:hoursSinceLastDefeat is nil.");
	end
end

Events.OnGameStart.Add(initData)
Events.OnGameStart.Add(initDataV2)
Events.EveryHours.Add(traumatizeTimer);	--enable after debugging
Events.EveryOneMinute.Add(traitHygienes)
--Events.EveryTenMinutes.Add(traumatizeTimer)	--disable after debugging
--Events.OnPlayerUpdate.Add(TestingFunction) 